package com.letwal.cmcvnd.anetwork

import com.letwal.cmcvnd.data.*
import com.letwal.cmcvnd.adata.feedback.ReqFeedbackSubmit
import com.letwal.cmcvnd.adata.home.getInviteFriendEarn.ReqGetInviteFriendEarn
import com.letwal.cmcvnd.adata.income.ReqExtractInviteIncome
import com.letwal.cmcvnd.adata.income.ReqGetInviteIncomeData
import com.letwal.cmcvnd.adata.login.ReqLogin
import com.letwal.cmcvnd.adata.login.ReqRegister
import com.letwal.cmcvnd.adata.user.ReqGetMyTransactions
import com.letwal.cmcvnd.adata.user.ReqGetUserWallet
import com.letwal.cmcvnd.adata.user.ReqSetWalletName
import com.letwal.cmcvnd.adata.withdraw.ReqWithdrawCreate
import com.letwal.cmcvnd.extend.toFullUrlPath
import okhttp3.MultipartBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.http.Part
import retrofit2.http.QueryMap
import java.lang.RuntimeException
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

object ApiUserNetwork {

    private val garlic_loanServiceApi = ApiServiceCreator.create<ApiUserService>()

    suspend fun getIpInfo() =
        garlic_loanServiceApi.getIpInfo(
            ApiUrl.PathGetIpInfo
        ).await()

    suspend fun getInviteFriendEarn(reqGetInviteFriendEarn: ReqGetInviteFriendEarn) =
        garlic_loanServiceApi.getInviteFriendEarn(
            ApiUrl.PathGetInviteFriendEarn.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetInviteFriendEarn
        ).await()

    suspend fun getInviteIncomeList(reqGetInviteFriendEarn: ReqGetInviteFriendEarn) =
        garlic_loanServiceApi.getInviteIncomeList(
            ApiUrl.PathGetInviteIncomeList.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetInviteFriendEarn
        ).await()

    suspend fun getTransferInDetail(reqGetInviteFriendEarn: ReqGetInviteFriendEarn) =
        garlic_loanServiceApi.getTransferInDetail(
            ApiUrl.PathGetTransferInDetail.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetInviteFriendEarn
        ).await()

    suspend fun getTransferInEarn(reqGetInviteFriendEarn: ReqGetInviteFriendEarn) =
        garlic_loanServiceApi.getTransferInEarn(
            ApiUrl.PathGetTransferInEarn.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetInviteFriendEarn
        ).await()

    suspend fun getTransferInEarnList(reqGetInviteFriendEarn: ReqGetInviteFriendEarn) =
        garlic_loanServiceApi.getTransferInEarnList(
            ApiUrl.PathGetTransferInEarnList.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetInviteFriendEarn
        ).await()

    suspend fun getTransferInExtractList(reqGetInviteFriendEarn: ReqGetInviteFriendEarn) =
        garlic_loanServiceApi.getTransferInExtractList(
            ApiUrl.PathGetTransferInExtractList.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetInviteFriendEarn
        ).await()

    suspend fun appVersion(reqBase: ReqBase) =
        garlic_loanServiceApi.appVersion(
            ApiUrl.PathAppVersion.toFullUrlPath(),
            reqBase
        ).await()

    suspend fun getCoins(reqBase: ReqBase) =
        garlic_loanServiceApi.getCoins(
            ApiUrl.PathGetCoins.toFullUrlPath(),
            ApiHeaderMap(),
            reqBase
        ).await()

    suspend fun feedbackSubmit(reqFeedbackSubmit: ReqFeedbackSubmit) =
        garlic_loanServiceApi.feedbackSubmit(
            ApiUrl.PathFeedbackSubmit.toFullUrlPath(),
            ApiHeaderMap(),
            reqFeedbackSubmit
        ).await()

    suspend fun extractInviteIncome(reqExtractInviteIncome: ReqExtractInviteIncome) =
        garlic_loanServiceApi.extractInviteIncome(
            ApiUrl.PathExtractInviteIncome.toFullUrlPath(),
            ApiHeaderMap(),
            reqExtractInviteIncome
        ).await()

    suspend fun extractRechargeIncome(reqExtractInviteIncome: ReqExtractInviteIncome) =
        garlic_loanServiceApi.extractRechargeIncome(
            ApiUrl.PathExtractRechargeIncome.toFullUrlPath(),
            ApiHeaderMap(),
            reqExtractInviteIncome
        ).await()

    suspend fun getInviteIncomeData(reqGetInviteIncomeData: ReqGetInviteIncomeData) =
        garlic_loanServiceApi.getInviteIncomeData(
            ApiUrl.PathGetInviteIncomeData.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetInviteIncomeData
        ).await()

    suspend fun getRechargeIncomeData(reqGetInviteIncomeData: ReqGetInviteIncomeData) =
        garlic_loanServiceApi.getRechargeIncomeData(
            ApiUrl.PathGetRechargeIncomeData.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetInviteIncomeData
        ).await()

    suspend fun detectUserInfo(reqLogin: ReqLogin) =
        garlic_loanServiceApi.detectUserInfo(
            ApiUrl.PathDetectUserInfo.toFullUrlPath(),
            ApiHeaderMap(),
            reqLogin
        ).await()

    suspend fun login(reqLogin: ReqLogin) =
        garlic_loanServiceApi.login(
            ApiUrl.PathLogin.toFullUrlPath(),
            ApiHeaderMap(),
            reqLogin
        ).await()

    suspend fun register(reqRegister: ReqRegister) =
        garlic_loanServiceApi.register(
            ApiUrl.PathRegister.toFullUrlPath(),
            ApiHeaderMap(),
            reqRegister
        ).await()

    suspend fun registerConfirm(reqRegister: ReqRegister) =
        garlic_loanServiceApi.registerConfirm(
            ApiUrl.PathRegisterConfirm.toFullUrlPath(),
            ApiHeaderMap(),
            reqRegister
        ).await()

    suspend fun getUserWallet(reqGetUserWallet: ReqGetUserWallet) =
        garlic_loanServiceApi.getUserWallet(
            ApiUrl.PathGetUserWallet.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetUserWallet
        ).await()

    suspend fun setWalletName(reqSetWalletName: ReqSetWalletName) =
        garlic_loanServiceApi.setWalletName(
            ApiUrl.PathSetWalletName.toFullUrlPath(),
            ApiHeaderMap(),
            reqSetWalletName
        ).await()

    suspend fun getUserAccounts(reqGetUserWallet: ReqGetUserWallet) =
        garlic_loanServiceApi.getUserAccounts(
            ApiUrl.PathGetUserAccounts.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetUserWallet
        ).await()

    suspend fun getMyInviteInfo(reqBase: ReqBase) =
        garlic_loanServiceApi.getMyInviteInfo(
            ApiUrl.PathGetMyInviteInfo.toFullUrlPath(),
            ApiHeaderMap(),
            reqBase
        ).await()

    suspend fun getMyTransactions(reqGetMyTransactions: ReqGetMyTransactions) =
        garlic_loanServiceApi.getMyTransactions(
            ApiUrl.PathGetMyTransactions.toFullUrlPath(),
            ApiHeaderMap(),
            reqGetMyTransactions
        ).await()

    suspend fun withdrawCreate(reqWithdrawCreate: ReqWithdrawCreate) =
        garlic_loanServiceApi.withdrawCreate(
            ApiUrl.PathWithdrawCreate.toFullUrlPath(),
            ApiHeaderMap(),
            reqWithdrawCreate
        ).await()

    suspend fun withdrawGetBalance(reqWithdrawCreate: ReqWithdrawCreate) =
        garlic_loanServiceApi.withdrawGetBalance(
            ApiUrl.PathWithdrawGetBalance.toFullUrlPath(),
            ApiHeaderMap(),
            reqWithdrawCreate
        ).await()

    suspend fun getRechargeIncomeConfig(reqBase: ReqBase) =
        garlic_loanServiceApi.getRechargeIncomeConfig(
            ApiUrl.PathGetRechargeIncomeConfig.toFullUrlPath(),
            ApiHeaderMap(),
            reqBase
        ).await()

    suspend fun uploadImage(
        @QueryMap map: Map<String, String>,
        @Part file: MultipartBody.Part,
    ) =
        garlic_loanServiceApi.uploadImage(
            ApiUrl.GARLICLOAN_PATH_UPLOAD_IMAGE.toFullUrlPath(),
            map,
            file
        ).await()

    private suspend fun <T> Call<T>.await(): T {
        return suspendCoroutine { continuation ->
            enqueue(object : Callback<T> {
                override fun onResponse(call: Call<T>, response: Response<T>) {
                    val body = response.body()
                    if (body != null) continuation.resume(body)
                    else continuation.resumeWithException(
                        RuntimeException("response body is null")
                    )
                }

                override fun onFailure(call: Call<T>, t: Throwable) {
                    continuation.resumeWithException(t)
                }
            })
        }
    }
}